package common;

import java.util.HashMap;
import java.lang.reflect.*;
import java.util.*;
import java.io.IOException;

public class JsonPersistence
{
    private Filer.Writer		fileWriter     = null;
    private HashMap<String, JsonObject> restoredObject = null;
    private HashMap<String, String>	transTable     = null;
    private ClassLoader			sysLoader      = ClassLoader.getSystemClassLoader();

    public JsonPersistence()
    {
	Filer	tmp = new Filer();
	fileWriter  = tmp.getWriter(null);
    }

    private String typeString(Object inst)
    {
	return inst.getClass().getCanonicalName();
    }

    private String recursiveToString(HashMap<String, String> src)
    {
	String result = "";

	for(String str: src.keySet())
	    {
		result += "\""+str+"\":"+src.get(str)+",\n";
	    }
	src.clear();
	return "{"+result.substring(0, result.length() - 2)+"}";
    }

    public String objTranslate(Object o)
    {
	if(o == null)
	    {
		return "null";
	    }

	String	oName  = o.getClass().getSimpleName();
	String	result = "";

	if (oName.equals("String") == true)
	    {
		return  "\""+(String)o+"\"";
	    }
	else if(oName.endsWith("[]") == true)
	    {
		result += "[";
		for(Object tmp : (Object[])o)
		    {
			result += objTranslate(tmp)+", ";
		    } 
		result = result.substring(0, result.length() - 2)+"]";
	    }
	else if(oName.equals("HashMap") == true)
	    {
		HashMap<Object, Object> hm = (HashMap<Object, Object>)o;
		
		result += "{";
		for(Object tmp : hm.keySet())
		    {
			result += objTranslate(tmp)+":"+objTranslate(hm.get(tmp))+", ";
		    }
		result = result.substring(0, result.length() - 2)+"}";
	    }
	else if(oName.equals("Vector") == true)
	    {
		Vector<Object>	vob  = (Vector<Object>)o;
		result		    += "[";

		for(Object tmp : vob)
		    {
			result += objTranslate(tmp)+", ";
		    } 
		result = result.substring(0, result.length() - 2)+"]";
	    }
	else
	    {
		result = "ERROR type";
	    }
	
	return result;
    }

    private String reprToFlat(String src)
    {
	return src.replaceAll("\n", "");
    }

    private String trimHeadTail(String src)
    {
	src = src.trim();
	return src.substring(1, src.length());
    }

    public Object fromJson(String jsonRepr)
    {
	return null;
    }

    public String toJson(Object inst)
    {
	HashMap<String, String> rst	 = new HashMap<String, String>();
	Class			soul	 = inst.getClass();
	String			bgtpName = "";

	rst.put("bgtpType", "\""+inst.getClass().getCanonicalName()+"\"");
	
	for(Field fld : soul.getDeclaredFields())
	    {
		try
		    {
			fld.setAccessible(true);
			if(fld.getName().equals("bgtpName") == true)
			    {
				bgtpName = (String)fld.get(inst);
			    }
			else
			    {
				rst.put(fld.getName(), objTranslate(fld.get(inst)));
			    }
		    }
		catch(Exception e)
		    {
			e.printStackTrace();
		    }
	    }
	return "\""+bgtpName+"\":"+recursiveToString(rst);
    }

    public Object summon(String name)
    {
	if(restoredObject == null)
	    {
		return null;
	    }
	
	if(restoredObject.containsKey(name) == false)
	    {
		return null;
	    }
	return _sub_summon(restoredObject.get(name));
    }

    //private String _summon_string(JsonObject jRepr)

    private Object _sub_summon(JsonObject jRepr)
    {
	String objType = jRepr.obj.getClass().getCanonicalName();

	// if(objType.equals("java.util.Array") == true)
	//     {
	// 	//надо проверить исходный объект на тип нужного поля
	// 	return jRepr.obj;
	//     }

	if(objType.equals("java.util.HashMap") == true)
	    {
		HashMap<String, JsonObject>	oRepr = (HashMap<String, JsonObject>)jRepr.obj;
		if(oRepr.containsKey("bgtpName") == false)
		    {
			return jRepr.obj;
		    }
		else
		    {

			try
			    {
				Object	result	    = Class.forName((String)_sub_summon(oRepr.get("bgtpType")));
				String	fldTypeName = "";
				Class	fldClass    = null;

				for(Field fld : result.getClass().getDeclaredFields())
				    {
					fldClass = fld.getClass();

					fld.setAccessible(true);
					fldTypeName = fldClass.getCanonicalName();

					if(fldTypeName.equals("java.util.Array"))
					    {
					    }
					else
					    {
						//fld.set(result, fldClass.cast(_sub_summon(oRepr.get(fld.getName()))));
					    }
				    }
				return result;
			    }
			catch(ClassNotFoundException cnfe)
			    {
				cnfe.printStackTrace();
			    }
		    }
	    }
	return null;
    }

    public Set<String> undump(String filename) throws JsonParserException,
					       JsonScanerException
    {
	JsonScaner	js = new JsonScaner();
	JsonParser	jp = new JsonParser();
	Filer		fl = new Filer();

	js.scan(fl.getReader(filename));
	
	try
	    {
		for(String item: js)
		    {
			jp.word(js.getState(), item);
		    } 

	    }
	catch(NoSuchElementException nsee)
	    {
		//
	    }
	restoredObject = (HashMap<String, JsonObject>)jp.getResult();
	return restoredObject.keySet();
    }

    public void dump(String tofile, Object ... items) 
    {
	fileWriter.openFile(tofile);
	fileWriter.writeLine("{");
	
	for(Object item : items)
	    {
		fileWriter.writeLine(toJson(item));
	    }

	fileWriter.writeLine("}");
	try
	    {
		fileWriter.close();
	    }
	catch(IOException ioe)
	    {
		ioe.printStackTrace();
	    }
    }
}